#include "CodeGenContext.hpp"
#include "MTBlock.hpp"
#include <iostream> //TODO remove me if not necessary

namespace MathematicaTranslator
{
	
	//each time create new file - destroy previous content
	CodeGenContext::CodeGenContext(const std::string& fileName) 
		:generated( fileName, std::ios::trunc) 
	{
		matrixIntAdd = false;
		matrixDoubleAdd = false;
		matrixIntMul = false;
		matrixDoubleMul = false;
		listIntAdd = false;
		listDoubleAdd = false;
		listIntMul = false;
		listDoubleMul = false;
		listDot = false;
		listBinOp = false;
		
		//TODO place common CUDA code to fresh file
	}

	CodeGenContext::~CodeGenContext()
	{
		generated.close();
	}

	void CodeGenContext::pushBlock(MTBlock* block)
	{
		blocks.push(new CodeGenBlock());
		blocks.top()->block = block;
	}

	void CodeGenContext::popBlock()
	{
		CodeGenBlock* top = blocks.top();
		blocks.pop();
		delete top;
	}

	std::ofstream *CodeGenContext::getStream(){
		return &generated;
	}

	void CodeGenContext::generateCode(MTBlock& root)
	{
		std::cout << "Generating code..." << std::endl;
		
		pushBlock(&root);

		generated << "#include \"cuda_runtime.h\"" << "\n";
		generated << "#include \"device_launch_parameters.h\"" << "\n";
		generated << "#include <stdio.h>" << "\n" << "\n";

		// postpone text generating in order to detect functions
		std::string *generetedCodeText = root.generateCode(*this);

		generated << "int main(int argc, char* argv[])" << std::endl;
		generated << "{" << std::endl;
		generated <<  *generetedCodeText << std::endl;
		generated << "return 0; " << std::endl;
		generated << "}" << std::endl;

		popBlock();

		std::cout << "Finished" << std::endl;
	}
}
